boost::less_than_comparable
前言
很多操作符都是可以从其他操作符自动推导出来,例如a != b可以从!(a == b)推导出来,因此原则上只需要定义少量的基本操作符,其他的操作符就可以 通过逻辑组合推导出来。
std::rel::ops
在C++98标准的std::rel_ops中定义了四个模板比较操作符!=、>、<=、>=,只需要为类定义==和<操作符,那么这四个操作符就可以自动实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream> #include <assert.h> #include <boost/logic/tribool.hpp> #include <boost/logic/tribool_io.hpp> #include <utility> class demo_class { public: demo_class(int n) : x(n) { } private: int x; public: friend bool operator<(const demo_class& lhs, const demo_class& rhs) { return lhs.x < rhs.x; } }; int main() { demo_class a(10), b(20); using namespace std::rel_ops; // 打开命名空间 std::cout << (a < b) << std::endl; std::cout << (b >= a) << std::endl; return 0; }
|
boost.opeartors库
同样地,boost.opeartors库允许用户在自己的类里仅定义少量的操作符(如<)就可以方便的自动生成其他操作符重载。
operators库由多个类组成,分别用来实现不同的运算概念,比如less_than_comparable定义了<系列操作符,left_shiftable定义了<<系列操作符。
- equality_comparable: 要求提供==,可自动实现!=,相等语义;
- less_than_comparable:要求提供<,可自动实现>,<=,>=;
- addable:要求提供+=,自动实现+;
- subtractable:要求提供-=,可自动实现-;
- incrementable:要求提供前置++,可自动实现后置++;
- decrementable:要求提供前置–,可自动实现后置–;
- equivalent:要求提供<,可自动实现==;
这些概念在库中以同名类的形式提供,用户需要以继承的方式来使用它们,继承的修饰符并不重要(private,public都可以),因为operator库里的类都是空类,没有成员变量和成员函数,仅定义了数个友元操作符函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <iostream> #include <assert.h> #include <boost/operators.hpp> class Point : public boost::less_than_comparable<Point> { public: explicit Point(int a = 0, int b = 0, int c = 0) : x(a), y(b), z(c) { } public: void print() const { std::cout << x << "," << y << "," << z << std::endl; } public: friend bool operator<(const Point& l, const Point& r) { return (l.x * l.x + l.y * l.y + l.z * l.z < r.x * r.x + r.y * r.y + r.z * r.z); } private: int x, y, z; };
|
在上面这段代码中,Point类中仅定义了一个友元operator<函数,其余的>、<=、>=均由less_than_comparable自动生成。
在使用operators库时需要注意,模板类型参数必须是子类本身,,特别是当子类本身也是个模板类的时候,不要错写成子类的模板参数或者子类不带模板参数的名称,否则会造成编译错误。在上面代码中,less_than_comparable的模板类型参数必须是Point类。